﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using Omu.AwesomeWebForms;
using Omu.AwesomeWebFormsDemo.Model;

namespace Omu.AwesomeWebFormsDemo.svc
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Aja
    {
        #region sample data

        public static readonly IList<Country> Countries = new List<Country>
        {
            new Country{Id = new Guid("16797552-87D5-478b-85B8-797D45C9315F"), Name = "Elwynn Forest" },
            new Country{Id = new Guid("26797552-87D5-478b-85B8-797D45C9315F"), Name = "Westfall" },
            new Country{Id = new Guid("36797552-87D5-478b-85B8-797D45C9315F"), Name = "Northrend" },
            new Country{Id = new Guid("46797552-87D5-478b-85B8-797D45C9315F"), Name = "Kalimdor" },
            new Country{Id = new Guid("56797552-87D5-478b-85B8-797D45C9315F"), Name = "Azeroth" },
        };

        public static readonly IList<Category> Categories = new List<Category>
         {
             new Category{Id=1, Name = "Fruits"},
             new Category{Id=2, Name = "Legumes"},
             new Category{Id=3, Name = "Vegetables"},
             new Category{Id=4, Name = "Nuts"},
             new Category{Id=5, Name = "Grains"},
         };

        public static readonly IList<Fruit> Fruits = new List<Fruit>
                                                 {
                                                     new Fruit{Id=1, Name = "Mango", Category = Categories[0]},
                                                     new Fruit{Id=2, Name = "Apple", Category = Categories[0]},
                                                     new Fruit{Id=3, Name = "Papaya", Category = Categories[0]},
                                                     new Fruit{Id=4, Name = "Banana", Category = Categories[0]},
                                                     new Fruit{Id=5, Name = "Cherry", Category = Categories[0]},

                                                     new Fruit{Id=10, Name = "Tomato", Category = Categories[1]},
                                                     new Fruit{Id=11, Name = "Potato", Category = Categories[1]},
                                                     new Fruit{Id=12, Name = "Cucumber", Category = Categories[1]},
                                                     new Fruit{Id=13, Name = "Onion", Category = Categories[1]},
                                                     new Fruit{Id=14, Name = "Carrot", Category = Categories[1]},
                                                     
                                                     new Fruit{Id=20, Name = "Celery", Category = Categories[2]},
                                                     new Fruit{Id=21, Name = "Broccoli", Category = Categories[2]},
                                                     new Fruit{Id=22, Name = "Artichoke", Category = Categories[2]},
                                                     new Fruit{Id=23, Name = "Cauliflower", Category = Categories[2]},
                                                     new Fruit{Id=24, Name = "Lettuce", Category = Categories[2]},
                                                     
                                                     new Fruit{Id=30, Name = "Hazelnuts", Category = Categories[3]},
                                                     new Fruit{Id=31, Name = "Chestnuts", Category = Categories[3]},
                                                     new Fruit{Id=32, Name = "Walnut", Category = Categories[3]},
                                                     new Fruit{Id=33, Name = "Almonds", Category = Categories[3]},
                                                     new Fruit{Id=34, Name = "Mongongo", Category = Categories[3]},
                                                     
                                                     new Fruit{Id=40, Name = "Rice", Category = Categories[4]},
                                                     new Fruit{Id=41, Name = "Wheat", Category = Categories[4]},
                                                     new Fruit{Id=42, Name = "Oats", Category = Categories[4]},
                                                     new Fruit{Id=43, Name = "Fonio", Category = Categories[4]},
                                                     new Fruit{Id=44, Name = "Barley", Category = Categories[4]},
                                                 };

        #endregion

        #region for AjaxCheckboxList

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> CategoriesCheckboxList(string v)
        {
            var keys = v.GetIntArray();
            return Categories.Select(o => new SelectListItem
                                 {
                                     Value = o.Id,
                                     Text = o.Name,
                                     Selected = keys.Contains(o.Id)
                                 });
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsCheckboxList(string v, string parent)
        {
            var keys = v.GetIntArray();
            var cats = parent.GetIntArray();

            return Fruits
                    .Where(f => cats.Contains(f.Category.Id))
                    .Select(o => new SelectListItem(o.Id, o.Name, keys.Contains(o.Id)));
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFrom2CatCheckboxList(string v, string c1, string c2)
        {
            var keys = v.GetIntArray();
            var c1s = c1.GetIntArray();

            return Fruits
                .Where(f => c1s.Contains(f.Category.Id) || f.Category.Id.ToString() == c2)
                .Select(o => new SelectListItem
                                 {
                                     Text = o.Name,
                                     Value = o.Id,
                                     Selected = keys.Contains(o.Id)
                                 });
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFromMultiListCheckboxList(string v, string parent)
        {
            var keys = v.GetIntArray();
            var pkeys = parent.GetIntArray();

            return Fruits
                .Where(f => pkeys.Contains(f.Category.Id))
                .Select(o => new SelectListItem
                {
                    Text = o.Name,
                    Value = o.Id,
                    Selected = keys.Contains(o.Id)
                });
        }

        #endregion

        #region for AjaxDropdown/AjaxRadiolist and for some other controls

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> InfDropdown(string v, string parent)
        {
            var l = new long[] { 1, 2, 3, 4, 5, 6, 7 };
            long add = 0;
            if (parent != null)
                add = long.Parse(parent);
            l = l.Select(i => i + add).ToArray();

            var list = l.Select(o => new SelectListItem
            {
                Text = o.ToString(),
                Value = o.ToString(),
                Selected = o == add
            });
            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> CountriesDropdown(string v)
        {
            var list = Countries.Select(o => new SelectListItem
                                                 {
                                                     Value = o.Id,
                                                     Text = o.Name,
                                                     Selected = v.ToLower() == o.Id.ToString().ToLower()
                                                 });
            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> CategoriesDropdown(string v)
        {
            return Categories.Select(o => new SelectListItem(o.Id, o.Name, v == o.Id.ToString()));
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsDropdown(string v, string parent)
        {
            var list = new List<SelectListItem> { new SelectListItem { Text = "not selected", Value = "" } };
            list.AddRange(Fruits
                .Where(f => f.Category.Id.ToString() == parent)
                .Select(o => new SelectListItem(o.Id, o.Name, v == o.Id.ToString())));
            return list;
        }

        //used for ajaxradiolist, exactly like FruitsDropdown ^, except without "not selected"
        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsList(string v, string parent)
        {
            return Fruits
                .Where(f => f.Category.Id.ToString() == parent)
                .Select(o => new SelectListItem(o.Id, o.Name, v == o.Id.ToString()));
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsWithParsDropdown(string v, string category, string hi, string ho)
        {
            var list = new List<SelectListItem> { new SelectListItem { Text = "not selected", Value = "" } };
            list.AddRange(Fruits.Where(f => f.Category.Id.ToString() == category)
                .Select(o => new SelectListItem
                                 {
                                     Text = o.Name,
                                     Value = o.Id,
                                     Selected = v == o.Id.ToString()
                                 }));
            list.Add(new SelectListItem { Value = hi, Text = ho });
            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFrom2CatDropdown(string v, string c1, string c2)
        {
            var list = new List<SelectListItem> { new SelectListItem { Text = "not selected", Value = "" } };

            list.AddRange(Fruits.Where(f => f.Category.Id.ToString() == c1 || f.Category.Id.ToString() == c2)
                .Select(o => new SelectListItem
                                                 {
                                                     Text = o.Name,
                                                     Value = o.Id,
                                                     Selected = v == o.Id.ToString()
                                                 }));
            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFrom2CatList(string v, string c1, string c2)
        {
            return Fruits
                .Where(f => f.Category.Id.ToString() == c1 || f.Category.Id.ToString() == c2)
                .Select(o => new SelectListItem
                                 {
                                     Text = o.Name,
                                     Value = o.Id,
                                     Selected = v == o.Id.ToString()
                                 });
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFromMultiDropdown(string v, string parent)
        {
            var ids = parent.GetIntArray();

            var list = new List<SelectListItem> { new SelectListItem { Text = "not selected", Value = "" } };
            list.AddRange(Fruits.Where(f => ids.Contains(f.Category.Id))
                .Select(o => new SelectListItem(o.Id, o.Name, v == o.Id.ToString())));

            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> FruitsFromMultiList(string v, string parent)
        {
            var ids = parent.GetIntArray();

            return Fruits
                .Where(f => ids.Contains(f.Category.Id))
                .Select(o => new SelectListItem
                              {
                                  Text = o.Name,
                                  Value = o.Id,
                                  Selected = v == o.Id.ToString()
                              });
        }

        #endregion

        #region Multilookup

        [WebGet]
        [OperationContract]
        public IEnumerable<KeyContent> FruitSelected(string selected)
        {
            var sel = selected.GetIntArray();
            return Fruits.Where(o => sel.Contains(o.Id))
                .Select(f => new KeyContent { Key = f.Id.ToString(), Content = f.Name });
        }

        [WebGet]
        [OperationContract]
        public LookupResult FruitSearch(string search, string selected, int page, bool isMoreClick)
        {
            search = (search ?? "").ToLower();
            var sel = selected.GetIntArray();

            var items = Fruits.Where(o => o.Name.ToLower().Contains(search) && !sel.Contains(o.Id))
                .Select(f => new KeyContent { Key = f.Id, Content = f.Name });

            const int pageSize = 5;
            IEnumerable<KeyContent> Items;

            //after postback we get page > 1 and isMoreClick = false, (this for the AjaxList, although this method is also used by the Lookup and MultiLookup)
            if (!isMoreClick && page > 1)
                Items = items.Take(page * pageSize);// so we return all data up to this page
            else
                Items = items.Skip((page - 1) * pageSize).Take(pageSize);

            return new LookupResult
                       {
                           Items = Items,
                           More = items.Count() > page * pageSize
                       };
        }

        [WebGet]
        [OperationContract]
        public LookupResult FruitSearchWithButtons(string search, string selected, int page)
        {
            search = (search ?? "").ToLower();
            var sel = selected.GetIntArray();
            var items = Fruits.Where(o => o.Name.ToLower().Contains(search) && !sel.Contains(o.Id))
                .Select(f => new KeyContent
                                 {
                                     Key = f.Id,
                                     Content = "<table><tr><td>" + f.Name + "</td><td><div class='awf-list-buttons'/></td></tr></table>",
                                     Encode = false // disable html encoding of Content ^
                                 });

            const int pageSize = 5;
            return new LookupResult
                       {
                           Items = items.Skip((page - 1) * pageSize).Take(pageSize),
                           More = items.Count() > page * pageSize,
                       };
        }

        [WebGet]
        [OperationContract]
        public KeyContent[] FruitGetMultiple(string v)
        {
            var ids = v.GetIntArray();
            return Fruits.Where(o => ids.Contains(o.Id)).Select(f => new KeyContent(f.Id, f.Name)).ToArray();
        }

        [WebGet]
        [OperationContract]
        public KeyContent FruitGet(string v)
        {
            var f = Fruits.Where(o => o.Id.ToString() == v).Single();
            return new KeyContent(f.Id, f.Name);
        }

        [WebGet]
        [OperationContract]
        public LookupResult FruitsByCategorySearch(string search, string selected, string parent)
        {
            search = (search ?? "").ToLower();
            var sel = selected.GetIntArray();

            var items = Fruits
                .Where(o => o.Name.ToLower().Contains(search)
                && !sel.Contains(o.Id)
                && parent == o.Category.Id.ToString())
                .Select(f => new KeyContent { Key = f.Id, Content = f.Name });
            return new LookupResult { Items = items };
        }

        [WebGet]
        [OperationContract]
        public LookupResult FruitsFrom2CatSearch(string search, string selected, string cat1, string cat2)
        {
            search = (search ?? "").ToLower();
            var selectedIds = selected.GetIntArray();
            var items = Fruits
                .Where(o => o.Name.ToLower().Contains(search)
                && !selectedIds.Contains(o.Id)
                && (cat1 == o.Category.Id.ToString() || cat2 == o.Category.Id.ToString()))
                .Select(f => new KeyContent(f.Id, f.Name));
            return new LookupResult { Items = items };
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<KeyContent> CategorySelected(string selected)
        {
            var sel = selected.GetIntArray();
            return Categories.Where(o => sel.Contains(o.Id))
                .Select(f => new KeyContent(f.Id, f.Name));
        }

        [WebGet]
        [OperationContract]
        public LookupResult CategorySearch(string search, string selected)
        {
            search = (search ?? "").ToLower();
            var sel = selected.GetIntArray();

            var items = Categories.Where(o => o.Name.ToLower().Contains(search) && !sel.Contains(o.Id))
                .Select(f => new KeyContent(f.Id, f.Name));
            return new LookupResult { Items = items };
        }

        [WebGet]
        [OperationContract]
        public KeyContent[] CategoryGetMultiple(string v)
        {
            var ids = v.GetIntArray();
            return Categories
                .Where(o => ids.Contains(o.Id))
                .Select(f => new KeyContent(f.Id, f.Name)).ToArray();
        }
        #endregion

        #region html encoding test
        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> CategoriesEncode(string v)
        {
            return new List<SelectListItem>{
                new SelectListItem{Value = "' <br> <hr> \" ' skdf '&", Text = "' <br> <hr> \" ' skdf '&"},
                new SelectListItem{Value = "' <br> <hr> \" ' skdf '&", Text = "' <br> <hr> \" ' skdf '&"},
                new SelectListItem{Value = "' <br> <hr> \" ' skdf '&", Text = "' <br> <hr> \" ' skdf '&"},
            };
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<SelectListItem> EncodeDropdown(string v)
        {
            var list = new List<SelectListItem>
                           {
                               new SelectListItem { Text = "hi's\"s<hr> ' \" sa", Value = "hi's\"s<hr>" },
                               new SelectListItem { Text = "<b>asd</b> ' \"s ", Value = "hi's\"s<hr>" },
                               new SelectListItem { Text = "hi's\"s<hr>", Value = "hi's\"s<hr>" },
                           };

            return list;
        }

        [WebGet]
        [OperationContract]
        public IEnumerable<KeyContent> EncodeSelected(string selected)
        {
            var items = new[]
                            {
                                new KeyContent("a '\"' <hr> <br>","a '\"' <hr> <br>"),
                                new KeyContent("a '\"' <hr> <br>","a '\"' <hr> <br>"),
                                new KeyContent("a '\"' <hr> <br>","a '\"' <hr> <br>")
                            };
            return items;
        }

        [WebGet]
        [OperationContract]
        public LookupResult EncodeSearch(string search, int page)
        {
            var items = new[]
                            {
                                new KeyContent("a \" <hr> <br>","a \" <hr> <br>"),
                                new KeyContent("a \"' <hr> <br>","a '\"' <hr> <br>"),
                                new KeyContent("a \"' <hr> <br>","a '\"' <hr> <br>"),
                            };

            const int pageSize = 1;
            return new LookupResult
            {
                Items = items.Skip((page - 1) * pageSize).Take(pageSize),
                More = items.Count() > page * pageSize
            };
        }


        [WebGet]
        [OperationContract]
        public IEnumerable<KeyContent> EncodeGetMultiple(string v)
        {
            return new[] { 
                new KeyContent("asdfa ' \" <hr><b>asdfa</b> ' '", "asdfa ' \" <hr><b>asdfa</b> ' '"),
                new KeyContent("asdfa ' \" <hr><b>asdfa</b> ' '", "asdfa ' \" <hr><b>asdfa</b> ' '"),
                new KeyContent("asdfa ' \" <hr><b>asdfa</b> ' '", "asdfa ' \" <hr><b>asdfa</b> ' '"),
            };
        }

        [WebGet]
        [OperationContract]
        public KeyContent EncodeGet(string v)
        {
            return new KeyContent("", "asdfa ' \" <hr><b>asdfa</b> ' '");
        }
        #endregion
    }

}